package xyz.eden.cloud.common.web.support.infrastructure.gateway;

import com.github.pagehelper.Page;
import lombok.extern.slf4j.Slf4j;
import xyz.eden.cloud.common.core.json.JsonTool;
import xyz.eden.cloud.common.web.support.domain.ability.model.BaseInfo;
import xyz.eden.cloud.common.web.support.domain.ability.model.BaseQuery;
import xyz.eden.cloud.common.web.support.domain.ability.model.PageInfo;
import xyz.eden.cloud.common.web.support.domain.gateway.BaseQueryGateway;
import xyz.eden.cloud.common.web.support.infrastructure.db.po.BasePO;
import xyz.eden.cloud.common.web.support.infrastructure.resource.BaseQueryResource;
import xyz.eden.cloud.common.web.support.infrastructure.resource.param.BaseQryParam;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
public abstract class AbstractBaseQueryGateway<Model extends BaseInfo, Query extends BaseQuery,
        PO extends BasePO, QryParam extends BaseQryParam, QueryResource extends BaseQueryResource<PO, QryParam>>
        implements BaseQueryGateway<Model, Query> {

    @Override
    public Model getInfoById(Long id) {
        log.info("AbstractBaseQueryGateway.getInfoById - id: [{}].", id);
        BaseQueryResource<PO, QryParam> queryResource = this.getQueryResource();
        PO po = queryResource.getInfoById(id);
        Model model = this.builderModelInfo(po);
        log.info("id: [{}] modelInfo: [{}].", id, JsonTool.toJsonStr(model));
        return model;
    }

    @Override
    public List<Model> getInfoByParam(Query query) {
        log.info("AbstractBaseQueryGateway.getInfoByParam - queryInfo: [{}].", JsonTool.toJsonStr(query));
        // 1. 拼装参数
        QryParam qryParam = this.builderQueryParam(query);
        // 2. 查询数据
        BaseQueryResource<PO, QryParam> queryResource = this.getQueryResource();
        List<PO> poList = queryResource.getListByParam(qryParam);
        // 3. 解析结果
        List<Model> modelList = Optional.ofNullable(poList).orElse(Collections.emptyList())
                .stream().map(this::builderModelInfo).collect(Collectors.toList());
        log.info("queryInfo: [{}], modelListInfo: [{}].", JsonTool.toJsonStr(query), JsonTool.toJsonStr(modelList));
        return modelList;
    }

    @Override
    public PageInfo<Model> getPageInfoByParam(int pageNumber, int pageSize, Query query) {
        log.info("AbstractBaseQueryGateway.getPageInfoByParam - pageInfo: [{}-{}], queryInfo: [{}].",
                pageNumber, pageSize, JsonTool.toJsonStr(query));
        // 1. 拼装参数
        pageNumber = pageNumber <= 0 ? 1 : pageNumber;
        pageSize = pageSize <= 0 ? 10 : pageSize;
        QryParam qryParam = this.builderQueryParam(query);
        // 2. 查询数据
        BaseQueryResource<PO, QryParam> queryResource = this.getQueryResource();
        Page<PO> page = queryResource.getListByPage(pageNumber, pageSize, qryParam);
        // 3. 解析结果
        PageInfo<Model> pageInfo = this.builderPage(page);
        log.info("pageInfo: [{}-{}], queryInfo: [{}], pageInfo: [{}].",
                pageNumber, pageSize, JsonTool.toJsonStr(query), JsonTool.toJsonStr(pageInfo));
        return pageInfo;
    }

    protected PageInfo<Model> builderPage(Page<PO> page) {
        if (Objects.isNull(page)) {
            return new PageInfo<>(1, 20, 0L, Collections.emptyList());
        }

        List<Model> modelList = Optional.ofNullable(page.getResult()).orElse(Collections.emptyList())
                .stream().map(this::builderModelInfo).collect(Collectors.toList());
        return new PageInfo<>(page.getPageNum(), page.getPageSize(), page.getTotal(), modelList);
    }

    public abstract QryParam builderQueryParam(Query query);

    protected abstract Model builderModelInfo(PO po);

    abstract QueryResource getQueryResource();
}
